﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace engine
{
    public class MarkerParser
    {
        #region 基础
        private ParagraphNode _paragraphNode;
        private GlobalConfig _globalConfig;
        private List<NodeBase> _children { get; set; }

        public bool ShouldThrowError { get; set; }
        public List<string> ErrorMessages { get; set; }

        public static object ParseText(string text, GlobalConfig globalConfig, bool withoutBeginMarker = false)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return text;
            }

            MarkerParser markerParser = new MarkerParser(text, globalConfig, withoutBeginMarker);
            return markerParser.Formula();
        }

        public MarkerParser(ParagraphNode paragraphNode, GlobalConfig globalConfig)
        {
            _paragraphNode = paragraphNode;
            _globalConfig = globalConfig;
            ErrorMessages = new List<string>();
            _children = new List<NodeBase>();
        }

        public MarkerParser(string text, GlobalConfig globalConfig, bool withoutBeginMarker = false)
        {
            TextRangeNode textRangeNode = new TextRangeNode("", null);
            if (withoutBeginMarker)
            {
                textRangeNode.Text = BeginMarker + text;
            }
            else
            {
                textRangeNode.Text = text;
            }
            ParagraphNode paragraphNode = new ParagraphNode(null);
            if (!string.IsNullOrWhiteSpace(textRangeNode.Text))
            {
                paragraphNode.AddChild(textRangeNode);
            }

            _paragraphNode = paragraphNode;
            _globalConfig = globalConfig;
            ErrorMessages = new List<string>();
            _children = new List<NodeBase>();
        }

        private void Error(string message = null)
        {
            if (ShouldThrowError)
            {
                throw new Exception(message);
            }
            else
            {
                ErrorMessages.Add(message);
            }
        }
        #endregion

        #region token相关
        private int beginChildIndex = 0;
        private int beginChildTextIndex = 0;
        private int endChildIndex = 0;
        private int endChildTextIndex = 0;

        private NodeBase CurrentNode
        {
            get
            {
                return _paragraphNode.Children[endChildIndex];
            }
        }
        
        private Token GetToken()
        {
            Token token = new Token();
            if(endChildIndex >= _paragraphNode.Children.Count)
            {
                Error("索引超出范围");
            }
            NodeBase nodeBase = _paragraphNode.Children[endChildIndex];
            if(nodeBase is PictureNode)
            {
                token.PictureNode = nodeBase as PictureNode;
            }
            else
            {
                TextRangeNode temp = nodeBase as TextRangeNode;
                TextRangeNode textRangeNode = new TextRangeNode(temp.Text[endChildTextIndex].ToString(), temp.Source);
                textRangeNode.CharactorFormat = temp.CharactorFormat;
                token.TextRangeNode = textRangeNode;
            }
            return token;
        }

        //private Token GetNextToken()
        //{
        //    Move
        //}

        //private Token GetPrevToken()
        //{

        //}

        private bool HasNextToken()
        {
            // 继续判断是否有下一个元素
            if (beginChildIndex + 1 < _paragraphNode.Children.Count)
            {
                return true;
            }
            // 如果不存在下一个元素了，判断当前元素
            if (beginChildIndex < _paragraphNode.Children.Count)
            {
                // 说明没有超出范围
                NodeBase nodeBase = _paragraphNode.Children[beginChildIndex];
                if(nodeBase is TextRangeNode)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                    // 是否有下一个字符
                    if(beginChildTextIndex + 1 < textRangeNode.Text.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void MoveToNextToken()
        {
            // 当前元素
            if (beginChildIndex < _paragraphNode.Children.Count)
            {
                // 说明没有超出范围
                NodeBase nodeBase = _paragraphNode.Children[beginChildIndex];
                if (nodeBase is TextRangeNode)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                    // 是否有下一个字符
                    if (beginChildTextIndex + 1 < textRangeNode.Text.Length)
                    {
                        beginChildTextIndex++;
                        endChildTextIndex = beginChildTextIndex;
                        return;
                    }
                }
            }
            // 下一个元素
            beginChildTextIndex = 0;
            endChildTextIndex = 0;
            while (true)
            {
                beginChildIndex++;
                endChildIndex = beginChildIndex;
                if (beginChildIndex < _paragraphNode.Children.Count)
                {
                    // 说明没有超出范围
                    NodeBase nodeBase = _paragraphNode.Children[beginChildIndex];
                    if (nodeBase is TextRangeNode)
                    {
                        // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                        TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                        if (textRangeNode.Text.Length > 0)
                        {
                            return;
                        }
                    }else if(nodeBase is PictureNode)
                    {
                        return;
                    }
                    else
                    {
                        Error("节点类型错误");
                    }
                }
                else
                {
                    Error("不存在token");
                }
            }
        }

        private bool HasNextMarkerToken()
        {
            // 判断是否有下一个元素
            if (endChildIndex + 1 < _paragraphNode.Children.Count)
            {
                return true;
                //NodeBase nodeBase = _paragraphNode.Children[endChildIndex + 1];
                //if(nodeBase is TextRangeNode)
                //{
                //    return true;
                //}
            }
            // 如果不存在下一个元素了，判断当前元素
            if (endChildIndex < _paragraphNode.Children.Count)
            {
                // 说明没有超出范围
                NodeBase nodeBase = _paragraphNode.Children[endChildIndex];
                if (nodeBase is TextRangeNode)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                    // 是否有下一个字符
                    if (endChildTextIndex + 1 < textRangeNode.Text.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void MoveToNextMarkerToken()
        {
            // 当前元素
            if (endChildIndex < _paragraphNode.Children.Count)
            {
                // 说明没有超出范围
                NodeBase nodeBase = _paragraphNode.Children[endChildIndex];
                if (nodeBase is TextRangeNode)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                    // 是否有下一个字符
                    if (endChildTextIndex + 1 < textRangeNode.Text.Length)
                    {
                        endChildTextIndex++;
                        return;
                    }
                }
            }
            // 下一个元素
            endChildTextIndex = 0;
            while (true)
            {
                endChildIndex++;
                if (endChildIndex < _paragraphNode.Children.Count)
                {
                    // 说明没有超出范围
                    NodeBase nodeBase = _paragraphNode.Children[endChildIndex];
                    if (nodeBase is TextRangeNode)
                    {
                        // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                        TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                        if (textRangeNode.Text.Length > 0)
                        {
                            return;
                        }
                    }
                    else if (nodeBase is PictureNode)
                    {
                        return;
                    }
                    else
                    {
                        Error("节点类型错误");
                    }
                }
                else
                {
                    Error("不存在token");
                }
            }
        }

        private void MoveToPrevMarkerToken()
        {
            if(endChildTextIndex > 0)
            {
                endChildTextIndex--;
            }
            else if(endChildIndex > 0)
            {
                endChildIndex--;
                NodeBase nodeBase = _paragraphNode.Children[endChildIndex];
                if(nodeBase is TextRangeNode)
                {
                    TextRangeNode textRangeNode = nodeBase as TextRangeNode;
                    endChildTextIndex = textRangeNode.Text.Length - 1;
                }
            }
            else
            {
                Error("无法移动到前一个token");
            }
        }
        #endregion

        #region marker相关
        public string BeginMarker = @"$";
        public string EndMarker = @"\";

        public void Parse()
        {
            if(_paragraphNode.Children.Count == 0)
            {
                return;
            }

            while (true)
            {
                if (JudgeBeginMarker())
                {
                    // 处理标记
                    Marker();
                    JudgeEndMarker();
                }
                else
                {
                    // 普通文本处理
                    Text();
                }
                if (!HasNextToken())
                {
                    break;
                }
                else
                {
                    MoveToNextToken();
                }
            }

            _paragraphNode.Children = new List<NodeBase>();
            foreach (var child in _children)
            {
                _paragraphNode.AddChild(child);
            }
        }

        private void Text()
        {
            Token token = GetToken();
            Appender(_children, token);
        }

        private void Appender(List<NodeBase> children, Token token)
        {
            if (!token.IsPicture && children.Count > 0 && children.Last() is TextRangeNode)
            {
                TextRangeNode last = children.Last() as TextRangeNode;
                if (last.FuncNode == null && last.Source == token.TextRangeNode.Source)
                {
                    last.Text += token.TextRangeNode.Text;
                    return;
                }
            }

            children.Add(token.Value);
        }

        private void Marker()
        {
            object value = Formula(_globalConfig.RootFuncNode, true);
            beginChildIndex = endChildIndex;
            beginChildTextIndex = endChildTextIndex;
            
            if(value is FuncNode)
            {
                FuncNode funcNode = value as FuncNode;
                UnitType? unitType = null;

                if (funcNode.IsVar)
                {
                    if (_globalConfig.TemplateConfig.Vars.ContainsKey(funcNode.FuncName))
                    {
                        VarItem varItem = _globalConfig.TemplateConfig.Vars[funcNode.FuncName];
                        unitType = varItem.UnitType;
                    }
                    else
                    {
                        Error(string.Format("变量{0}未定义", funcNode.FuncName));
                    }
                }
                else
                {
                    if (_globalConfig.RootFuncNode.TemplateFunc.HasFunc(funcNode.FuncName))
                    {
                        unitType = _globalConfig.RootFuncNode.TemplateFunc.GetFuncType(funcNode.FuncName);

                        if (unitType == UnitType.Any && funcNode.Config != null)
                        {
                            unitType = funcNode.Config.UnitType;
                        }
                    }
                    else
                    {
                        Error(string.Format("函数{0}未定义", funcNode.FuncName));
                    }
                }

                if (unitType == UnitType.TextRange ||
                    unitType == UnitType.Array || 
                    unitType == UnitType.String || 
                    unitType == UnitType.Boolean || 
                    unitType == UnitType.Number || 
                    unitType == UnitType.Object ||
                    unitType == UnitType.Any)
                {
                    Token token = GetToken();
                    TextRangeNode node = new TextRangeNode(null, token.TextRangeNode.Source);
                    node.FuncNode = funcNode;
                    node.CharactorFormat = token.TextRangeNode.CharactorFormat;
                    _children.Add(node);
                }
                else if (unitType == UnitType.Picture)
                {
                    NodeBase nodeBase = new PictureNode(null);
                    nodeBase.FuncNode = funcNode;
                    _children.Add(nodeBase);
                }
                else if (unitType == UnitType.Paragraph)
                {
                    _paragraphNode.FuncNode = funcNode;
                }
                else if (unitType == UnitType.Body)
                {
                    NodeBase parent = _paragraphNode;
                    while (parent != null)
                    {
                        if (parent.ContainerType == ContainerType.Body)
                        {
                            parent.FuncNode = funcNode;
                            break;
                        }
                        else
                        {
                            parent = parent.Parent;
                        }
                    }
                }
                else
                {
                    var parent = _paragraphNode.Parent;
                    while (parent != null)
                    {
                        if (parent.MappedUnitType == unitType)
                        {
                            parent.FuncNode = funcNode;
                            break;
                        }
                        else
                        {
                            parent = parent.Parent;
                        }
                    }
                }
                // 为了保证包含标记的段落始终被渲染
                _paragraphNode.MustRender = true;
            }
        }

        private bool JudgeBeginMarker()
        {
            // 判断是不是标记符，包括多字符，判断结束标记等。
            Token token = GetToken();
            if (token.IsPicture)
            {
                return false;
            }
            else
            {
                if(token.TextRangeNode.Text == BeginMarker)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        private void JudgeEndMarker()
        {
            if (string.IsNullOrWhiteSpace(EndMarker))
            {
                // 如果没有结束符啥也不用干
            }
            else if(HasNextMarkerToken())
            {
                // 如果有结束符，判断下一个token是不是结束符，如果是则跳过，不是则不需要管
                MoveToNextMarkerToken();
                Token token = GetToken();
                if(!token.IsPicture && token.TextRangeNode.Text == EndMarker)
                {

                }
                else
                {
                    MoveToPrevMarkerToken();
                }
            }

            beginChildIndex = endChildIndex;
            beginChildTextIndex = endChildTextIndex;
        }

        private object Formula(FuncNode parent = null, bool isTop = false)
        {
            object value = null;

            if(parent == null)
            {
                parent = _globalConfig.RootFuncNode;
            }

            MoveToNextMarkerToken();
            Token token = GetToken();

            if (token.IsPicture)
            {
                // 图片常量
                if (isTop)
                {
                    Error("图片无需标记");
                }
                else
                {
                    value = Pic();
                }
            }
            else
            {
                string c = token.TextRangeNode.Text;
                if(c == "(")
                {
                    // 代码块
                    value = CodeBlock(parent);
                }
                else if(c == "`")
                {
                    // 字符串常量
                    if (isTop)
                    {
                        Error("字符串无需标记");
                    }
                    else
                    {
                        value = Str();
                    }
                }
                else if ("0123456789".Contains(c))
                {
                    // 数字常量
                    if (isTop)
                    {
                        Error("数字无需标记");
                    }
                    else
                    {
                        value = Num();
                    }
                }
                else if("abcdefghizklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".Contains(c))
                {
                    // 变量或者函数
                    value = VarOrFunc(parent);
                }
                else if(c == "@")
                {
                    // for对象
                    value = For(parent);
                }
                else
                {
                    Error("错误的标记公式");
                }
            }

            return value;
        }

        private object CodeBlock(FuncNode parent)
        {
            object value = Formula(parent);
            JudgeToken(")");
            return value;
        }

        private PictureNode Pic()
        {
            // 处理图片变量
            Token token = GetToken();
            return token.PictureNode;
        }

        private FullString Str()
        {
            List<NodeBase> value = new List<NodeBase>();
            while (true)
            {
                MoveToNextMarkerToken();
                Token token = GetToken();

                if (!token.IsPicture && token.TextRangeNode.Text == "`")
                {
                    break;
                }
                else
                {
                    Appender(value, token);
                }
            }
            return new FullString{
                Items = value.Select(r => r.RenderValue(null)[0]).ToList()
            };
        }

        private int Num()
        {
            Token token = GetToken();
            int value = int.Parse(token.TextRangeNode.Text);
            
            while (true)
            {
                if (!HasNextMarkerToken())
                {
                    break;
                }

                MoveToNextMarkerToken();
                token = GetToken();

                if (!token.IsPicture && "0123456789".Contains(token.TextRangeNode.Text))
                {
                    value = value * 10 + int.Parse(token.TextRangeNode.Text);
                }
                else
                {
                    MoveToPrevMarkerToken();
                    break;
                }
            }
            return value;
        }

        private FuncNode VarOrFunc(FuncNode parent)
        {
            FuncNode funcNode = new FuncNode();
            parent = CurrentNode.GetCurrentFuncNode(parent);
            parent.AddChild(funcNode);
            MoveToPrevMarkerToken();
            string name = Name();
            
            if (!HasNextMarkerToken())
            {
                funcNode.IsVar = true;
                funcNode.FuncName = name;
            }
            else
            {
                MoveToNextMarkerToken();
                Token token = GetToken();

                if (token.TextRangeNode.Text == "(")
                {
                    // 函数
                    funcNode.IsVar = false;
                    funcNode.FuncName = name;
                    funcNode.Params = Paras(funcNode);
                    JudgeToken(")");
                }
                else
                {
                    // 变量
                    MoveToPrevMarkerToken();
                    funcNode.IsVar = true;
                    funcNode.FuncName = name;
                }
            }

            // 
            if (funcNode.IsVar)
            {
                if (_globalConfig.TemplateConfig.Vars.ContainsKey(funcNode.FuncName))
                {
                    funcNode.Config = _globalConfig.TemplateConfig.Vars[funcNode.FuncName];
                }
                else
                {
                    var temp = funcNode.GetDataWithParent(funcNode.FuncName);
                    if (temp != null)
                    {
                        funcNode.Config = temp.Config;
                    }
                    else
                    {
                        Error(string.Format("变量{0}未定义", funcNode.FuncName));
                    }
                }
            }
            else
            {
                if (!_globalConfig.RootFuncNode.TemplateFunc.HasFunc(funcNode.FuncName))
                {
                    Error(string.Format("函数{0}未定义", funcNode.FuncName));
                }
            }

            while (HasNextMarkerToken())
            {
                MoveToNextMarkerToken();
                Token token = GetToken();

                if (token.TextRangeNode.Text == ".")
                {
                    funcNode = ObjectProp(parent, funcNode, funcNode.FuncName);
                }
                else if (token.TextRangeNode.Text == "[")
                {
                    funcNode = ArrayItem(parent, funcNode, funcNode.FuncName);
                }
                else
                {
                    MoveToPrevMarkerToken();
                    break;
                }
            }

            return funcNode;
        }

        private FuncNode ObjectProp(FuncNode parent, object obj, string objName)
        {
            string prop = Name();
            FuncNode func = new FuncNode();
            parent = CurrentNode.GetCurrentFuncNode(parent);
            parent.AddChild(func);
            func.IsVar = false;
            func.FuncName = TemplateFuncNames.PropOfObject;
            func.Params = new List<object> { obj, objName, prop };
            
            if(obj is FuncNode)
            {
                var temp = obj as FuncNode;
                func.AddChild(temp);
                if(temp.Config != null && temp.Config.UnitType == UnitType.Object)
                {
                    var temp2 = temp.Config as ObjectVarItem;
                    if (temp2.CustomType.Props.ContainsKey(prop))
                    {
                        var temp3 = temp2.CustomType.Props[prop];
                        func.Config = temp3;
                    }
                }
            }

            return func;
        }

        private FuncNode ArrayItem(FuncNode parent, object arr, string arrName)
        {
            object index = Formula(parent);
            JudgeToken("]");

            FuncNode func = new FuncNode();
            parent = CurrentNode.GetCurrentFuncNode(parent);
            parent.AddChild(func);
            func.IsVar = false;
            func.FuncName = TemplateFuncNames.ItemOfArray;
            func.Params = new List<object> { arr, arrName, index };
            return func;
        }

        private string Name()
        {
            string value = "";
            while (true)
            {
                if (value.Length > 0 && !HasNextMarkerToken())
                {
                    break;
                }

                MoveToNextMarkerToken();
                Token token = GetToken();
                if (!token.IsPicture && "_-abcdefghizklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".Contains(token.TextRangeNode.Text))
                {
                    value += token.TextRangeNode.Text;
                }
                else
                {
                    MoveToPrevMarkerToken();
                    break;
                }
            }
            return value;
        }

        private List<object> Paras(FuncNode parent)
        {
            List<object> value = new List<object>();

            MoveToNextMarkerToken();
            Token token = GetToken();

            if(!token.IsPicture && token.TextRangeNode.Text == ")")
            {
                // 说明没有参数
                MoveToPrevMarkerToken();
                return value;
            }
            else
            {
                MoveToPrevMarkerToken();
                value.Add(Formula(parent));
                value = value.Concat(NextPara(parent)).ToList();
                return value;
            }
        }

        private List<object> NextPara(FuncNode parent)
        {
            List<object> value = new List<object>();

            while (true)
            {
                MoveToNextMarkerToken();
                Token token = GetToken();
                if (!token.IsPicture && token.TextRangeNode.Text == ",")
                {
                    value.Add(Formula(parent));
                }
                else
                {
                    MoveToPrevMarkerToken();
                    break;
                }
            }

            return value;
        }

        private For For(FuncNode parent)
        {
            object list = Formula(parent);
            JudgeToken("@");
            string itemName = Name();
            MoveToNextMarkerToken();
            Token token = GetToken();
            string indexName = null;
            if(!token.IsPicture && token.TextRangeNode.Text == "@")
            {
                indexName = Name();
            }
            else
            {
                MoveToPrevMarkerToken();
            }

            // 构造for对象
            For f = new For();
            f.ListFunc = list as FuncNode;
            f.ItemName = itemName;
            f.IndexName = indexName;

            // 
            if(f.ListFunc is FuncNode)
            {
                ArrayVarItem arrayVarItem = f.ListFunc.Config as ArrayVarItem;
                parent.SetData(itemName, new DataItem ( null, arrayVarItem.CustomType.DefaultConfig ));
            }

            return f;
        }

        private void JudgeToken(string c)
        {
            MoveToNextMarkerToken();
            Token token = GetToken();
            if(token.IsPicture)
            {
                MoveToNextMarkerToken();
                Error(string.Format("希望得到字符{0}，但得到图片.", c));
            }
            else
            {
                if(c == token.TextRangeNode.Text)
                {
                }
                else
                {
                    MoveToNextMarkerToken();
                    Error(string.Format("希望得到字符{0}，但得到字符{1}.", c, token.TextRangeNode.Text));
                }
            }
        }
        #endregion
    }

    public class Token
    {
        public bool IsPicture
        {
            get
            {
                return PictureNode != null;
            }
        }

        public NodeBase Value
        {
            get
            {
                if (IsPicture)
                {
                    return PictureNode;
                }
                else
                {
                    return TextRangeNode;
                }
            }
        }

        public PictureNode PictureNode { get; set; }
        public TextRangeNode TextRangeNode { get; set; }
    }
}
